/*-
 * Copyright (c) 2006, 2007 FTS Team
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the FTS Team nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *      Retriever.hpp
 *
 * $FTS$
 */
#ifndef _RETRIEVER_HPP__
#define _RETRIEVER_HPP__ 1


/**
  @file Retriever.hpp
  @brief Information retriever
*/
#include <FTS.hpp>
#include <STLVector.hpp>

namespace FTSS // FullTextSearchSystem
{

//FWD
class DocumentInfoStorage;
class DocumentStorage;
class IRConfig;
class InvIndexBPlusStorage;
class LemmatizerInterface;
class QueryOperator;
class QueryToken;
class SnippetCollector;
class StopWords;
class TimeProfiler;

/**
  @class Retriever Retriever.hpp <Retriever.hpp>
  @brief Retriever - search word in data storage
*/
class Retriever
{
public:
	/**
	  @brief Constructor
	  @param oIConfig - FTSS configuration
	  @param oILemmatizer - lemmatizer interface
	  @param pIStorage - Interface to data storage
	  @param pIDocumentInfoStorage - document properties storage
	  @param pIDocumentStorage - parsed document storage
	  @param oIStopWords - Stop words database
	  @param oITimeProfiler - time profiler
	*/
	Retriever(IRConfig            & oIConfig,
	          LemmatizerInterface & oILemmatizer,
	          //InvIndexStorage     * pIStorage,
	          InvIndexBPlusStorage     * pIStorage,
	          DocumentInfoStorage * pIDocumentInfoStorage,
	          DocumentStorage     * pIDocumentStorage,
	          StopWords           & oIStopWords,
	          TimeProfiler        & oITimeProfiler);

	/**
	  @brief Destructor
	*/
	~Retriever() throw();

	/**
	  @brief Search word in data Storage
	  @param sQuery - query to search
	  @param iQueryLength - query length
	  @param oSnippetCollector - snippet collector for search result
	*/
	void Search(CCHAR_P sQuery, Size_t iQueryLength, SnippetCollector & oSnippetCollector);

private:
	/** Search engine configuration   */
	IRConfig            & oConfig;
	/** Lemmatizer                    */
	LemmatizerInterface & oLemmatizer;
	/** Data storage                  */
	//InvIndexStorage     * pStorage;
	InvIndexBPlusStorage     * pStorage;
	/** Document properties database  */
	DocumentInfoStorage * pDocumentInfoStorage;
	/** Parsed document storage       */
	DocumentStorage     * pDocumentStorage;
	/** Stop words database           */
	StopWords           & oStopWords;
	/** Time profiler                 */
	TimeProfiler        & oTimeProfiler;

	/**
	  @brief Join two lists
	  JoinLists( [1 2 3 4 5], [ 0 2 4 6 8 ] ) = [ 0 1 2 3 4 5 6 8 ]
	  @param vFirst - first vector, result of operation will be placed here
	  @param vSecond - second vector
	*/
	void JoinLists(STLW::vector<DocumentEntry *>  & vFirst,
	               STLW::vector<DocumentEntry *>  & vSecond);

	/**
	  @brief Merge two lists
	  MergeLists( [1 2 3 4 5], [ 0 2 4 6 8 ] ) = [ 2 4 ]
	  @param vFirst - first vector, result of operation will be placed here
	  @param vSecond - second vector
	*/
	void MergeLists(STLW::vector<DocumentEntry *>  & vFirst,
	                STLW::vector<DocumentEntry *>  & vSecond);

	/**
	  @brief Merge two lists with quorum
	  MergeLists( [1 2 3 4 5] [ 0 2 4 6 8 ] ) = [ 1 2 4 5 ]
	  @param vFirst - first vector, result of operation will be placed here
	  @param vFirstWeight - weights of first vector elements
	  @param vSecond - second vector
	  @param dWeight - weight of term
	*/
	void MergeQuorumLists(STLW::vector<DocumentEntry *>  & vFirst,
	                      STLW::vector<W_FLOAT>          & vFirstWeight,
	                      STLW::vector<DocumentEntry *>  & vSecond,
	                      W_FLOAT                         dWeight);
	/**
	  @brief OR Query
	  @param pOperator - root node of subtree
	*/
	void ORQuery(QueryOperator * pOperator);

	/**
	  @brief NOT Query
	  @param pOperator - root node of subtree
	*/
	void NOTQuery(QueryOperator * pOperator);

	/**
	  @brief AND Query
	  @param pOperator - root node of subtree
	*/
	void ANDQuery(QueryOperator * pOperator);

	/**
	  @brief AND Query with quorum
	  @param pOperator - root node of subtree
	  @param dSoftness - quorum softness
	  @param dStopWordWeight - weight of stop word
	*/
	void ANDQuorumQuery(QueryOperator * pOperator,
	                    const W_FLOAT & dSoftness,
	                    const W_FLOAT & dStopWordWeight);

	/**
	  @brief Process query tree
	  @param pToken - root token
	  @param dSoftness - quorum softness
	  @param dStopWordWeight - weight of stop word
	*/
	void ProcessTree(QueryToken          * pToken,
	                 const W_FLOAT       & dSoftness,
	                 const W_FLOAT       & dStopWordWeight);

	/**
	  @brief Recursive tree descending
	  @param pToken - root token
	  @param iLevel - recursion level
	  @param dSoftness - quorum softness parameter
	  @param dStopWordWeight - stop word weight
	  @return Found Document ID
	*/
	DocumentId_t DescendTree(QueryToken    * pToken,
	                         INT_32        & iLevel,
	                         const W_FLOAT & dSoftness,
	                         const W_FLOAT & dStopWordWeight);

#ifdef _DEBUG
	/**
	  @brief Print contents of tree if debugging mode is enabled
	  @param pToken - root token
	*/
	void PrintTreeDebug(QueryToken * pToken);

	/**
	  @brief Recursive tree descending
	  @param pToken - root token
	  @param iLevel - recursion level
	*/
	void DescendTreeDebug(QueryToken * pToken, INT_32 & iLevel);
#endif

};

} // namespace FTSS
#endif // _RETRIEVER_HPP__
// End.
